package org.dizena.common.trace.feign.handler;

import feign.Response;
import feign.Util;
import org.dizena.common.base.enums.EnumHeaderKey;
import org.dizena.common.base.enums.EnumLogLevel;
import org.dizena.common.except.BusinessException;
import org.dizena.common.logger.bean.LogInfo;
import org.dizena.common.logger.bean.LogRpcEvent;
import org.dizena.common.utils.ReqUtil;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.http.HttpStatus;

import java.io.IOException;

public class FeignErrorDecoder implements feign.codec.ErrorDecoder {

    final ApplicationEventPublisher publisher;

    public FeignErrorDecoder(ApplicationEventPublisher publisher) {
        this.publisher = publisher;
    }

    @Override
    public Exception decode(String method, Response response) {
        LogInfo logInfo = new LogInfo();
        logInfo.setTraceId(ReqUtil.getTrace());
        logInfo.setClientIp(ReqUtil.getAllHeaderMap().get(EnumHeaderKey.REQUEST_IP));
        logInfo.setResponseTime(System.currentTimeMillis());

        if (response.status() != HttpStatus.OK.value()) {
            if (response.status() == HttpStatus.SERVICE_UNAVAILABLE.value()) {
                try {
                    String error = Util.toString(response.body().asReader());
                    logInfo.setException(response.status() + " " + method + " " + error);
                } catch (IOException e) {
                    logInfo.setException(response.status() + " " + method);
                }
            } else {
                logInfo.setException(response.status() + " " + method);
            }
        }
        logInfo.setException(response.status() + " " + method);
        publisher.publishEvent(new LogRpcEvent(this, logInfo, EnumLogLevel.ERROR));
        return new BusinessException(response.status(), logInfo.getException());
    }
}